package com.hzw.saas.service.rss.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzw.saas.api.rss.IJournalCatalogService;
import com.hzw.saas.api.rss.IJournalCatalogUserService;
import com.hzw.saas.api.rss.IJournalCustomService;
import com.hzw.saas.api.rss.bo.JournalCatalogBO;
import com.hzw.saas.api.rss.bo.JournalCatalogUserBO;
import com.hzw.saas.api.user.IUserRightsService;
import com.hzw.saas.api.user.bo.UserRightsBO;
import com.hzw.saas.common.util.MapperUtil;
import com.hzw.saas.common.util.SnowFlakeUtil;
import com.hzw.saas.service.rss.mapper.JournalCatalogMapper;
import com.hzw.saas.service.rss.mapper.JournalCatalogUserMapper;
import com.hzw.saas.service.rss.model.JournalCatalog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 期刊站点的目录分类 服务实现类
 * </p>
 *
 * @author sonam
 * @since 2021-06-30
 */
@Service("journalCatalogService")
public class JournalCatalogServiceImpl extends ServiceImpl<JournalCatalogMapper, JournalCatalog> implements IJournalCatalogService, IService<JournalCatalog> {


    @Resource(name = "journalCatalogUserService")
    private IJournalCatalogUserService journalCatalogUserService;

    @Autowired
    private IUserRightsService userRightsService;

    @Autowired
    private JournalCatalogMapper journalCatalogMapper;

    @Autowired
    private JournalCatalogUserMapper journalCatalogUserMapper;

    @Resource(name = "journalCustomService")
    private IJournalCustomService journalCustomService;

    @Override
    public JournalCatalogBO getById(String pid) {
        if(StrUtil.isBlank(pid)) return null;
        return MapperUtil.nf().map(super.getById(pid), JournalCatalogBO.class);
    }

    @Override
    public List<JournalCatalogBO> query(JournalCatalogBO journalCatalogBO) {
        if(Objects.isNull(journalCatalogBO)) return MapperUtil.nf().mapAsList(this.list(), JournalCatalogBO.class);
        JournalCatalog journalCatalog = MapperUtil.nf().map(journalCatalogBO, JournalCatalog.class);
        List<JournalCatalog> journals = this.list(Wrappers.<JournalCatalog>query().setEntity(journalCatalog));
        return MapperUtil.nf().mapAsList(journals, JournalCatalogBO.class);
    }

    @Override
    public void update(JournalCatalogBO journalCatalogBO) {
        if(journalCatalogBO == null) return;
        JournalCatalog journal = MapperUtil.nf().map(journalCatalogBO, JournalCatalog.class);
        this.updateById(journal);
    }

    @Override
    public void delete(JournalCatalogBO journalCatalogBO) {
        if(journalCatalogBO == null) return;
        this.remove(Wrappers.<JournalCatalog>query().setEntity(MapperUtil.nf().map(journalCatalogBO, JournalCatalog.class)));
    }

    @Override
    public void delete(String pid) {
        if(StrUtil.isBlank(pid)) return;
        this.removeById(pid);
    }

    /**
     * 校验是否超过目录层级
     * @param catalogBO
     */
    void verificationCatalogLevel(JournalCatalogBO catalogBO){
        if (catalogBO.getParentId()== null || catalogBO.getParentId().equals("0")){
            return;
        }
        List<JournalCatalog> list = this.lambdaQuery().eq(JournalCatalog::getPid, catalogBO.getParentId()).list();
        list.forEach(journalCatalog -> {
            if (journalCatalog.getParentId() != null && !journalCatalog.getParentId().equals("0")){
                throw new RuntimeException("当前目录层级已经达到两级，无法继续新增下级");
            }
        });
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBatch(List<JournalCatalogBO> journalCatalogBOS,String userId){
        if(CollectionUtil.isEmpty(journalCatalogBOS)) return;
        //判断用户会员等级
        UserRightsBO userRightsByUser = userRightsService.getUserRightsByUser(userId);
        if (userRightsByUser != null && !userRightsByUser.getLevelId().equals("1")){
            ArrayList<JournalCatalogUserBO> addBo = new ArrayList<>();
            journalCatalogBOS.forEach(catalogBO -> {
                verificationCatalogLevel(catalogBO);
                String pid = catalogBO.getPid();
                String s = SnowFlakeUtil.nextIdStr();
                JournalCatalogUserBO journalCatalogUserBO = new JournalCatalogUserBO();
                journalCatalogUserBO.setCatalogName(catalogBO.getName());
                journalCatalogUserBO.setCatalogId(pid);
                if (StrUtil.isBlank(pid)) {
                    catalogBO.setPid(s);
                    journalCatalogUserBO.setCatalogId(s);
                }

                addBo.add(journalCatalogUserBO);
                if(StrUtil.isBlank(catalogBO.getParentId())) {
                    catalogBO.setParentId("0");
                }
            });
            this.saveBatch(MapperUtil.nf().mapAsList(journalCatalogBOS, JournalCatalog.class));
            //关联表新增关联数据，给站点指定用户
            if (CollectionUtil.isNotEmpty(addBo)){
                journalCatalogUserService.addCatalogUser(addBo,userId);
            }
        }
    }

    @Override
    public void updateJournalCatalog(JournalCatalogBO journalCatalogBO, String userId) {

    }



    @Override
    @Transactional(rollbackFor = Exception.class)
    public void moveCatalogHeadNode(String headId, String newParent, String userId){
        String userIdByCatalogId = journalCatalogUserService.findUserIdByCatalogId(headId);
        if (userIdByCatalogId.equals(userId)){
            JournalCatalogBO head = getById(headId);
            JournalCatalogBO newHead = getById(newParent);
            if (newHead == null || (!newHead.getParentId().equals("0")&&newHead.getParentId() != null)){
                throw new RuntimeException("目录层级最大为2级");
            }
            List<JournalCatalogBO> journalCatalogs = newHead.getJournalCatalogs();
            if (CollectionUtil.isNotEmpty(journalCatalogs)){
                List<String> collect = journalCatalogs.stream().map(JournalCatalogBO::getName).collect(Collectors.toList());
                if (collect.contains(head.getName())){
                    throw new RuntimeException(head.getName()+"与目录中有重名");
                }
                head.setParentId(newHead.getPid());
                this.update(head);
            }

        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteJournalCatalogBO(String headId, String userId) {
        JournalCatalogUserBO userIdByCatalogId = journalCatalogUserService.findById(headId);
        if (userIdByCatalogId != null && userIdByCatalogId.getUserId().equals(userId)) {
            journalCatalogUserService.deleteCatalogUserTree(headId);
        }
    }

    @Override
    public List<JournalCatalogBO> getCatalogByUserId(String userId) {
        List<JournalCatalogUserBO> journalCatalogUser = journalCatalogUserService.findJournalCatalogUser(userId);
        if (CollectionUtil.isNotEmpty(journalCatalogUser)){
            ArrayList<JournalCatalogBO> JournalCatalogBOs = new ArrayList<>();
            journalCatalogUser.forEach(journalCatalogUserBO -> {
                JournalCatalogBO journalCatalogBO = new JournalCatalogBO();
                journalCatalogBO.setParentId(journalCatalogUserBO.getParentId());
                journalCatalogBO.setPid(journalCatalogUserBO.getPid());
                journalCatalogBO.setName(journalCatalogUserBO.getCatalogName());
                JournalCatalogBOs.add(journalCatalogBO);
            });
            return buildCatalog(JournalCatalogBOs,"0");
          //  }
        }
        return null;
    }

    @Override
    public List<JournalCatalogBO> getCatalogByIds(List<String> catalogIds) {
        List<JournalCatalog> journalCatalogs = this.lambdaQuery()
            .in(CollectionUtil.isNotEmpty(catalogIds), JournalCatalog::getPid, catalogIds).list();
        List<JournalCatalogBO> journalCatalogBOS = MapperUtil.nf().mapAsList(journalCatalogs, JournalCatalogBO.class);
        for (int i = 0 ; i < journalCatalogBOS.size(); i ++) {
            // 补齐夫节点
            journalCatalogBOS.set(i, getParentCatalog(journalCatalogBOS.get(i)));
        }

        return journalCatalogBOS;
    }

    /**
     * 查询某个分类的夫节点id
     * @param journalCatalogBO
     * @return
     */
    private JournalCatalogBO getParentCatalog(JournalCatalogBO journalCatalogBO) {
        if(journalCatalogBO == null) {
            return null;
        }

        if (Objects.equals(journalCatalogBO.getParentId(), "0")) {
            return journalCatalogBO;
        }

        JournalCatalogBO catalogBO = this.getById(journalCatalogBO.getParentId());
        if(catalogBO == null) {
            return journalCatalogBO;
        }
        catalogBO.setJournalCatalogs(new ArrayList<>());
        catalogBO.getJournalCatalogs().add(journalCatalogBO);
        return getParentCatalog(catalogBO);
    }

    @Override
    public List<JournalCatalogBO> findJournalCatalogTree() {
        List<JournalCatalog> list = this.lambdaQuery().eq(JournalCatalog::getIsDelete, 0).
            eq(JournalCatalog::getCatalogType,1).list();
        List<JournalCatalogBO> journalCatalogBOS = MapperUtil.nf().mapAsList(list, JournalCatalogBO.class);
        return buildCatalog(journalCatalogBOS,"0");
    }

    @Override
    public List<JournalCatalogBO> findPublicCatalogIds() {
        List<JournalCatalog> list = this.lambdaQuery().eq(JournalCatalog::getCatalogType, 1).list();
        if (CollectionUtil.isNotEmpty(list)){
            return MapperUtil.nt().mapAsList(list,JournalCatalogBO.class);
        }
        return Collections.emptyList();
    }


    private static JournalCatalogBO findChildren(JournalCatalogBO treeNode, List<JournalCatalogBO> treeNodes) {
        for (JournalCatalogBO it : treeNodes) {
            if (treeNode.getPid().equals(it.getParentId())) {
                if (treeNode.getJournalCatalogs() == null) {
                    treeNode.setJournalCatalogs(new ArrayList<>());
                }
                treeNode.getJournalCatalogs().add(findChildren(it, treeNodes));
            }
        }
        return treeNode;
    }

    @Override
    public  List<JournalCatalogBO> buildCatalog(List<JournalCatalogBO> journalCatalogBOS, String parentId) {
        List<JournalCatalogBO> trees = new ArrayList();
        for (JournalCatalogBO treeNode : journalCatalogBOS) {
            if (parentId.equals("0")) {
                if (parentId.equals(treeNode.getParentId())) {
                    trees.add(findChildren(treeNode, journalCatalogBOS));
                }
            } else {
                if (parentId.equals(treeNode.getPid())) {
                    trees.add(findChildren(treeNode, journalCatalogBOS));
                }
            }

        }
        return trees;
    }

    @Override
    public List<JournalCatalogBO> findByCatalogsWithTree(List<String> collect) {
        if (CollectionUtil.isNotEmpty(collect)){
            List<JournalCatalog> list = this.lambdaQuery().in(JournalCatalog::getPid, collect).list();
            if (CollectionUtil.isNotEmpty(list)){
                List<JournalCatalogBO> journalCatalogBOS = MapperUtil.nf().mapAsList(list, JournalCatalogBO.class);
                return  journalCatalogBOS;
            }
        }
        return Collections.emptyList();
    }

}
